package com.xz.diagnosisOrder.service.impl;

import java.math.BigDecimal;
import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.xz.common.exception.ServiceException;
import com.xz.common.utils.DateUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.diagnosisOrder.domain.DiagnosisRefundOrderDetail;
import com.xz.diagnosisOrder.domain.DiagnosisTreatmentOrder;
import com.xz.diagnosisOrder.dto.DiagnosisTreatmentOrderConsumablesDto;
import com.xz.diagnosisOrder.dto.DiagnosisTreatmentOrderSaveDto;
import com.xz.diagnosisOrder.utils.DiagnosisOrderUtils;
import com.xz.diagnosisOrder.vo.DiagnosisTreatmentOrderConsumablesVo;
import com.xz.patient.domain.PatientInfo;
import com.xz.product.mapper.ProductMapper;
import com.xz.product.vo.ProductRelatedInfoVo;
import com.xz.purchase.domain.PurchaseProduct;
import com.xz.purchase.mapper.PurchaseProductMapper;
import com.xz.purchase.service.IPurchaseProductService;
import com.xz.purchase.vo.ChoosePurchaseProductVo;
import com.xz.repertory.domain.RepertoryFlow;
import com.xz.repertory.service.IRepertoryFlowService;
import com.xz.supplierOrder.domain.SupplierOrderDetail;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xz.diagnosisOrder.mapper.DiagnosisTreatmentOrderConsumablesMapper;
import com.xz.diagnosisOrder.domain.DiagnosisTreatmentOrderConsumables;
import com.xz.diagnosisOrder.service.IDiagnosisTreatmentOrderConsumablesService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 就诊单耗品Service业务层处理
 *
 * @author xz
 * @date 2024-03-30
 */
@Service
public class DiagnosisTreatmentOrderConsumablesServiceImpl extends ServiceImpl<DiagnosisTreatmentOrderConsumablesMapper, DiagnosisTreatmentOrderConsumables> implements IDiagnosisTreatmentOrderConsumablesService {
  @Autowired
  private DiagnosisTreatmentOrderConsumablesMapper diagnosisTreatmentOrderConsumablesMapper;
  @Autowired
  private ProductMapper productMapper;
  @Autowired
  private PurchaseProductMapper purchaseProductMapper;
  @Autowired
  private IRepertoryFlowService repertoryFlowService;

  /**
   * 查询就诊单耗品列表
   *
   * @param diagnosisTreatmentOrderConsumables 就诊单耗品
   * @return 就诊单耗品
   */
  @Override
  public List<DiagnosisTreatmentOrderConsumables> selectDiagnosisTreatmentOrderConsumablesList(DiagnosisTreatmentOrderConsumables diagnosisTreatmentOrderConsumables) {
    return diagnosisTreatmentOrderConsumablesMapper.selectDiagnosisTreatmentOrderConsumablesList(diagnosisTreatmentOrderConsumables);
  }

  /**
   * 查询就诊单耗品列表(根据就诊单id)
   *
   * @param treatmentOrderId 就诊单id
   * @return 就诊单耗品
   */
  @Override
  public List<DiagnosisTreatmentOrderConsumables> selectByTreatmentOrderId(Long treatmentOrderId) {
    LambdaQueryWrapper<DiagnosisTreatmentOrderConsumables> wrapper = Wrappers.lambdaQuery(DiagnosisTreatmentOrderConsumables.class);
    wrapper.eq(DiagnosisTreatmentOrderConsumables::getTreatmentOrderId, treatmentOrderId);
    return list(wrapper);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void saveForOrder(DiagnosisTreatmentOrder order, DiagnosisTreatmentOrderSaveDto orderDto) {

    if (CollectionUtils.isEmpty(orderDto.getConsumables())) {
      return;
    }
    // 药品记录
    List<DiagnosisTreatmentOrderConsumables> list = new ArrayList<>();
    // 库存流水记录 -- 作用是追踪库存流水的日志
    List<RepertoryFlow> repertoryFlows = new ArrayList<>();
    orderDto.getConsumables().forEach(dto -> {
      // 查询库存信息
      List<PurchaseProduct> purchaseProducts = getPurchaseProducts(dto);
      if (CollectionUtils.isEmpty(purchaseProducts)) {
        throw new ServiceException("药品库存数量不足，请选择其他药品");
      }
      // 查询商品信息
      ProductRelatedInfoVo product = productMapper.getProductRelatedInfo(dto.getProductId());
      if (null == product) {
        throw new ServiceException("药品已删除，请选择其他药品");
      }

      // 开始扣减库存，并且生成流水记录放入res中
      List<PurchaseProduct> res = repertoryFlowService.convertFlowData(purchaseProducts, dto.getProductNum(), order.getOrderNo(), order.getId());
      res.forEach(purchase -> {
        repertoryFlows.add(initRepertoryFlow(order, orderDto, purchase));
      });

      //初始化药品记录,并且放入药品记录的list中
      list.add(init(order, dto, product, purchaseProducts));
    });
    //开始处理库存流水日志(typ: 2.出库；storageType：24.诊疗领药)
    repertoryFlowService.saveBatch(repertoryFlows);
    //批量保存
    this.saveBatch(list);
  }


  /**
   * 检索对应的采购商品明细
   *
   * @param dto （dto，前端传入的药品信息）
   * @return
   */
  private List<PurchaseProduct> getPurchaseProducts(DiagnosisTreatmentOrderConsumablesDto dto) {
    //开始检索出对应的商品明细对象
    PurchaseProduct queryProductParam = new PurchaseProduct();
    queryProductParam.setProductName(dto.getProductName());
    queryProductParam.setProductParam(dto.getProductParam());
    queryProductParam.setWarehouseId(dto.getWarehouseId());
    queryProductParam.setBatchNumber(dto.getBatchNumber());
    queryProductParam.setBatchDate(dto.getBatchDate());
    queryProductParam.setValidity(dto.getValidity());
    queryProductParam.setSupplierId(dto.getSupplierId());
    List<PurchaseProduct> purchaseProductList = purchaseProductMapper.getListByParam(queryProductParam);
    if (CollectionUtils.isEmpty(purchaseProductList)) {
      throw new ServiceException("提交失败，药品库存不足或药品信息已更改，请选择其他药品");
    }
    return purchaseProductList;
  }


  /**
   * 库存流水
   *
   * @param order               诊疗单
   * @param orderDto            诊疗单（dto，前端传入的开单信息）
   * @param purchase 库存扣减的流水记录
   * @return
   */
  private RepertoryFlow initRepertoryFlow(DiagnosisTreatmentOrder order, DiagnosisTreatmentOrderSaveDto orderDto, PurchaseProduct purchase) {
    RepertoryFlow repertoryFlow=new RepertoryFlow();
    repertoryFlow.setFlowType(2);//typ: 2.出库
    repertoryFlow.setStorageType(24);//storageType：24.诊疗领药

    // 库存信息
    repertoryFlow.setPurchaseProductId(purchase.getId());
    repertoryFlow.setProductId(purchase.getProductId());
    repertoryFlow.setBusinessId(purchase.getBusinessId());
    repertoryFlow.setProductEncoded(purchase.getProductEncoded());
    repertoryFlow.setProductName(purchase.getProductName());
    repertoryFlow.setProductParameter(purchase.getProductParam());
    repertoryFlow.setBatchNumber(purchase.getBatchNumber());
    repertoryFlow.setValidity(purchase.getValidity());
    repertoryFlow.setSupplierId(purchase.getSupplierId());
    repertoryFlow.setSupplierName(purchase.getSupplierName());
    repertoryFlow.setWarehouseName(purchase.getWarehouseName());
    // 金额信息
    repertoryFlow.setQuantity(purchase.getInventoryQuantity());
    repertoryFlow.setCostPrice(purchase.getCostPrice());
    repertoryFlow.setCostAmount(purchase.getCostPrice().multiply(BigDecimal.valueOf(purchase.getInventoryQuantity())));
    repertoryFlow.setPrice(BigDecimal.ZERO);
    repertoryFlow.setAmount(BigDecimal.ZERO);
    repertoryFlow.setDiscount(BigDecimal.ZERO);

    // 订单信息
    repertoryFlow.setNumber(order.getOrderNo());
    PatientInfo patient = orderDto.getPatient();
    repertoryFlow.setMemberId(patient.getId());

    String memberName = DiagnosisOrderUtils.getPatientInfo(patient.getPatientName(), patient.getSex(),patient.getBirthday());
    repertoryFlow.setMemberName(memberName);
    repertoryFlow.setTenantId(order.getTenantId());
    repertoryFlow.setDeptId(order.getDeptId());
    repertoryFlow.setCreateBy(order.getCreateBy());
    repertoryFlow.setCreateTime(order.getCreateTime());
    return repertoryFlow;
  }

  /**
   * 初始化药品记录
   *
   * @param order               诊疗单
   * @param dto                 （dto，前端传入的药品信息）
   * @param product             商品信息
   * @param purchaseProductList 库存信息
   * @return
   */
  private DiagnosisTreatmentOrderConsumables init(DiagnosisTreatmentOrder order, DiagnosisTreatmentOrderConsumablesDto dto,
                                                  ProductRelatedInfoVo product, List<PurchaseProduct> purchaseProductList) {

    DiagnosisTreatmentOrderConsumables consumables = new DiagnosisTreatmentOrderConsumables();
    // 商品信息
    consumables.setTreatmentOrderId(order.getId());
    consumables.setProductId(product.getId());
    consumables.setProductName(product.getProductName());
    consumables.setProductPrice(product.getPrice());
    consumables.setProductEncoded(product.getEncoded());
    consumables.setManufacturer(product.getManufacturer());
    consumables.setRegistrationNo(product.getRegistrationNo());
    consumables.setBrandName(product.getBrandName());
    consumables.setProductCategory(product.getProductCategory());
    consumables.setUnit(product.getUnitName());
    // 库存信息
    PurchaseProduct purchaseProduct = purchaseProductList.get(0);
    consumables.setProductParam(purchaseProduct.getProductParam());
    consumables.setBatchNumber(purchaseProduct.getBatchNumber());
    consumables.setBatchDate(purchaseProduct.getBatchDate());
    consumables.setValidity(purchaseProduct.getValidity());
    consumables.setWarehouseId(purchaseProduct.getWarehouseId());
    consumables.setWarehouseName(purchaseProduct.getWarehouseName());
    consumables.setSupplierId(purchaseProduct.getSupplierId());
    consumables.setSupplierName(purchaseProduct.getSupplierName());
    // 前端传入需要扣减的数量
    consumables.setProductNum(dto.getProductNum());
    // 填充创建人信息
    consumables.setCreateBy(order.getCreateBy());
    consumables.setCreateTime(order.getCreateTime());
    consumables.setTenantId(order.getTenantId());
    consumables.setDeptId(order.getDeptId());
    return consumables;
  }

  /**
   * 获取药品Vo集合
   * @param id
   * @return
   */
  @Override
  public List<DiagnosisTreatmentOrderConsumablesVo> getDiagnosisTreatmentOrderConsumablesVo(Long id) {
    List<DiagnosisTreatmentOrderConsumables> consumables = selectByTreatmentOrderId(id);
    List<DiagnosisTreatmentOrderConsumablesVo> consumablesVos = null;
    if(!CollectionUtils.isEmpty(consumables)){
      //转成VO后赋值
      consumablesVos = consumables.stream().map(consumable ->{
        DiagnosisTreatmentOrderConsumablesVo consumablesVo = new DiagnosisTreatmentOrderConsumablesVo();
        BeanUtils.copyProperties(consumable,consumablesVo);
        return consumablesVo;
      }).collect(Collectors.toList());
    }
    return consumablesVos;
  }
}
